package lerry.nape.factory;

import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import lerry.nape.body.CustomBody;
import nape.geom.Vec2;
import nape.phys.Body;
import nape.phys.BodyType;
import nape.phys.Material;
import nape.shape.Circle;
import nape.shape.Polygon;
import nape.shape.Shape;
import nape.space.Space;


/**
 * ...
 * @author lxq
 */
class BodyFactory {
	
	public static function rectangle(space:Space=null,x:Float=0,y:Float=0,width:Float=50,height:Float=50,type:Int=1,material:Material=null):Body {
		var b:Body = new Body(null,Vec2.get(x,y) );
		if (type == 1) {
			b.type = BodyType.DYNAMIC;
		}else if (type==2){
			b.type = BodyType.KINEMATIC;
		}else {
			b.type = BodyType.STATIC;
		}
		var poly:Polygon = new Polygon(Polygon.box(width, height),material);
		poly.body = b;
		if (space!=null) {
			b.space = space;
		}
		return b;
	}
	
	public static function circle(space:Space=null,x:Float=0,y:Float=0,radius:Float=50,type:UInt=1,material:Material=null):Body {
			var circle:Body=new Body(null,Vec2.get(x,y));
			switch(type) {
				case 1:
					circle.type = BodyType.DYNAMIC;
				case 2:
					circle.type = BodyType.KINEMATIC;
				case 3:
					circle.type = BodyType.STATIC;
			}
			circle.shapes.add(new Circle(radius,null,material));
			if(space!=null)
				circle.space=space;
			return circle;
	}
	
	public static function regular(space:Space=null,x:Float=0,y:Float=0,xRadius:Float=50,yRadius:Float=50,segments:UInt=5,type:UInt=1,material:Material=null):Body {
		var reg:Body = new Body(null, Vec2.get(x, y));
		switch(type) {
				case 1:
					reg.type = BodyType.DYNAMIC;
				case 2:
					reg.type = BodyType.KINEMATIC;
				case 3:
					reg.type = BodyType.STATIC;
			}
		var p:Polygon = new Polygon(Polygon.regular(xRadius, yRadius, segments),material);
		p.body = reg;
		reg.align();
		if (space != null) {
			reg.space = space;
		}
		return reg;
	}
	
	public static function fromPolygon(poly:Polygon,space:Space=null,type:UInt=1):Body {
		var body:Body=new Body();
		switch(type) {
			case 1:
				body.type=BodyType.DYNAMIC;
			case 2:
				body.type=BodyType.KINEMATIC;
			case 3:
				body.type=BodyType.STATIC;
		}
		body.shapes.add(poly);
		if (space!=null) {
			body.space=space;
		}
		return body;
	}
	
	public static function fromDisplayObject(disobj:DisplayObject,position:Vec2=null,space:Space=null,type:UInt=1,useGraphic:Bool=true,graphicContainer:DisplayObjectContainer=null):Body {
		var cb:CustomBody=new CustomBody(disobj,space,4,8,useGraphic,graphicContainer);
		var body:Body = cb.result;
		switch(type) {
			case 1:
				body.type=BodyType.DYNAMIC;
			case 2:
				body.type=BodyType.KINEMATIC;
			case 3:
				body.type=BodyType.STATIC;
		}
		if (position != null) {
			body.position=position;
		}
		if (space!=null) {
			body.space=space;
		}
		return body;
	}
	
	
	public static function removeBody(target:Body,removeGraphic:Bool=true):Void {
		target.space.bodies.remove(target);
		target.shapes.clear();
		if(target.userData.graphic && removeGraphic) {
			var g:DisplayObject=target.userData.graphic;
			if(g.parent!=null){
				g.parent.removeChild(g);
			}	
			g=null;
		}
		target=null;
	}
	public static function border(space:Space=null,width:Float=800,height:Float=600,material:Material=null):Body {
        var border = new Body(BodyType.STATIC);
        border.shapes.add(new Polygon(Polygon.rect(0, 0, -2, width)));
        border.shapes.add(new Polygon(Polygon.rect(0, 0, width, -2)));
        border.shapes.add(new Polygon(Polygon.rect(width, 0, 2, height)));
        border.shapes.add(new Polygon(Polygon.rect(0, height, width, 2)));
        border.space = space;
        border.debugDraw = false;
		if (material!=null) {
			for (i in 0...border.shapes.length) {
				border.shapes.at(i).material = material;
			}
		}
        return border;
    }
	
	public static function setGraphic(body:Body,gra:DisplayObject,offset:Vec2=null,resize:Bool=true,add:Bool=true):Void {
		body.userData.graphic = gra;
		if (resize) {
			gra.width = body.bounds.width;
			gra.height = body.bounds.height;
		}
		offset != null?body.userData.graphicOffset = offset:body.userData.graphicOffset = Vec2.get( 0, 0);
		
		if (add) {
			NapeEngine.source.addChild(gra);
		}
	}
	/**
	 * 
	 * @param	body
	 * @param	density 密度 ,物体在其中受到的阻力大小
	 * @param	viscosity 黏性阻力,越小，表示阻力越小，物体进入后，反弹力越大
	 */
	public static function setBodyToFluid(body:Body,density:Float=3,viscosity:Float=6,gravity:Vec2=null):Void {
		body.shapes.foreach(function(s:Shape):Void {
			s.fluidEnabled = true;
			s.fluidProperties.density = density;
			s.fluidProperties.viscosity = viscosity;
			s.fluidProperties.gravity = gravity;
		});
	}
}